package com.kuang.design.creation.sigle;

/**
 * 单例模式就是确保一个类只有一个实例
 * 单例类必须自己创建自己的唯一实例
 * 并提供一个全局访问点来访问该实例。
 */
public class Person {
    private String name;
    private String age;

    private static Person kuang;
    private final static Person hu = new Person();
    private static Person lazyOne;
    private static Person lazyTow;
    private static Person lazyThree;
    private volatile static  Person lazyFour;

    //构造器私有，外部不能实例化，只能内部实例化，且对外提供一个实例化方法
    private Person() {
        System.out.println("创建了person对象");
    }

    //以下方法实际使用之选择一个即可

    //提供给外部的方法，要匡匡只有一个，要静态返回就需要一个静态的PerSon变量kuang；
    //饿汉式
    public static Person kuang() {
        return kuang;
    }

    //饿汉式
    public static Person hu() {
        return hu;
    }

    //懒汉式(非线程安全版)
    public static Person lazyOne() {
        if (lazyOne == null) {
            lazyOne = new Person();
        }
        return lazyOne;
    }

    //懒汉式(线程安全版1)--锁太大，效率低
    public static synchronized Person lazyTow() {
        if (lazyTow == null) {
            lazyTow = new Person();
        }
        return lazyTow;
    }


    //懒汉式(线程安全版2)--锁住了
    public static Person lazyThree() {
        synchronized (Person.class) {
            if (lazyThree == null) {

                lazyThree = new Person();
            }
        }

        return lazyThree;
    }

    //懒汉式(线程安全版3)--
    //双重检查锁+内存可见性
    public static Person lazyFour() {

        if (lazyFour == null) {
            //1、把锁加在这里粒度最小，但是带来一个新问题，若两个线程同时为null会同时进入这把锁，相当于无效锁
            synchronized (Person.class) {
                //解决方案再检查一遍，且在变量上加volatile
                if (lazyFour == null) {
                    lazyFour = new Person();
                }
            }
        }

        return lazyFour;
    }

}
